/* ***************************************************************************
 **    input.c
 **
 **  Project      :
 **  Target       :
 **  Description  :
 **
 **
 **  Compiler     : HI-TECH C  Version 9.80
 **  IDE          : MPLABX v1.80
 **  Created      : June 21, 2013
 **
 **  Master
 ** ***************************************************************************/

/*****************************************************************************
 **HEADER FILES
 *****************************************************************************/

//Compiler-Standard
#include <htc.h>
#include <stdint.h>        /* For uint8_t definition */
#include <stdbool.h>       /* For true/false definition */
#include <string.h>

//Project
#include "global.h"
#include "input.h"
#include "shift_register.h"
#include "display.h"
#include "swI2C.h"
#include "DS1307.h"
/*****************************************************************************
 **VARIABLES
 *****************************************************************************/

/*****************************************************************************
 **FUNCTIONS
 *****************************************************************************/

void InputTime(void){

    uint8_t daysInMonth;

    DisplayScrollText(inputStrings[0]);

    DisplayScrollText(inputStrings[1]);
    dateTime.f.hour = GetNumber(1, 12);

    DisplayScrollText(inputStrings[2]);
    dateTime.f.min = GetNumber(0, 59);

    DisplayScrollText(inputStrings[3]);
    dateTime.f.sec = 0;

    DisplayScrollText(inputStrings[4]);
    dateTime.f.year = GetNumber(0, 99);

    DisplayScrollText(inputStrings[5]);
    dateTime.f.mon = GetMonth();

    switch (dateTime.f.mon) {
        case 1: daysInMonth = 31;
            break;
        case 2: daysInMonth = 28;
            break;
        case 3: daysInMonth = 31;
            break;
        case 4: daysInMonth = 30;
            break;
        case 5: daysInMonth = 31;
            break;
        case 6: daysInMonth = 30;
            break;
        case 7: daysInMonth = 31;
            break;
        case 8: daysInMonth = 31;
            break;
        case 9: daysInMonth = 30;
            break;
        case 10: daysInMonth = 31;
            break;
        case 11: daysInMonth = 30;
            break;
        case 12: daysInMonth = 31;
            break;
    }

    // If the month is February, check for leap year
    if (dateTime.f.mon == 2 && (dateTime.f.year % 400 == 0 ||
            (dateTime.f.year % 4 == 0 && dateTime.f.year % 100 != 0))) {
        daysInMonth = 29;
    }

    DisplayScrollText(inputStrings[6]);
    dateTime.f.mday = GetNumber(1, daysInMonth);

    DisplayScrollText(inputStrings[7]);
    dateTime.f.wday = GetDay();

    RTCSetTime();
    DisplayScrollText(inputStrings[8]);

}

uint8_t GetNumber(uint8_t min, uint8_t max){

    unsigned char done = FALSE;

    uint8_t result = min;
    uint8_t currentNumber = min;

    DisplayNumber(currentNumber);

    while(!done) {
        
        // ------------------------------------------------------------------------------
        // Get the current button states (with on and off debouncing)

        ReadButtonState();

        // ------------------------------------------------------------------------------
        // Adjust the result and display

        if (currentButtonState[UP] == ON && result < max) result++;

        if (currentButtonState[DOWN] == ON && result > min) result--;    

        if (currentButtonState[ENTER] == ON) done = TRUE;

        // Display the current number if it has changed
        if (currentNumber != result) {
            DisplayNumber(result);
            currentNumber = result;
        }
    }

    return result;
}

uint8_t GetDay(void){

    unsigned char min = 1;
    unsigned char max = 7;
    unsigned char done = FALSE;

    unsigned char result = min;
    unsigned char currentNumber = min;

    DisplayString(dow_str[result]);

    while(!done) {
        
        // ------------------------------------------------------------------------------
        // Get the current button states (with on and off debouncing)

        ReadButtonState();

        // ------------------------------------------------------------------------------
        // Adjust the result and display

        if (currentButtonState[UP] == ON && result < max) result++;

        if (currentButtonState[DOWN] == ON && result > min) result--;

        if (currentButtonState[ENTER] == ON) done = TRUE;

        // Display the current day if it has changed
        if (currentNumber != result) {
            DisplayString(dow_str[result]);
            currentNumber = result;
        }
    }

    return result;
}

uint8_t GetMonth(void){

    unsigned char min = 1;
    unsigned char max = 12;

    unsigned char done = FALSE;

    unsigned char result = min;
    unsigned char currentNumber = min;

    DisplayString(month_str[result]);

    while(!done) {

        // ------------------------------------------------------------------------------
        // Get the current button states (with on and off debouncing)

        ReadButtonState();

        // ------------------------------------------------------------------------------
        // Adjust the result and display

        if (currentButtonState[UP] == ON && result < max) result++;

        if (currentButtonState[DOWN] == ON && result > min) result--;

        if (currentButtonState[ENTER] == ON) done = TRUE;

        // Display the current day if it has changed
        if (currentNumber != result) {
            DisplayString(month_str[result]);
            currentNumber = result;
        }
    }

    return result;
}

void ReadButtonState(void){

    uint8_t readState[3];

    readState[UP] = UP_BUTTON;
    readState[DOWN] = DOWN_BUTTON;
    readState[ENTER] = ENTER_BUTTON;

    for (uint8_t button = 0; button < 3; button++) {
        if (currentButtonState[button] == OFF && readState[button] == OFF) {
            if (buttonDebounceCounter[button] > DEBOUNCE_AMOUNT) {
                currentButtonState[button] = ON;
                buttonDebounceCounter[button] = 0;
            } else buttonDebounceCounter[button]++;
        } else if (currentButtonState[button] == ON && readState[button] == ON) {
            if (buttonDebounceCounter[button] > DEBOUNCE_AMOUNT) {
                currentButtonState[button] = OFF;
                buttonDebounceCounter[button] = 0;
            } else buttonDebounceCounter[button]++;
        } else buttonDebounceCounter[button] = 0;
    }
}